﻿using Application.Adapter;
using Domain;
using Domain.Enums;
using Domain.Models;
using MediatR;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using TouchSocket.Core;
using TouchSocket.Sockets;

namespace Application.Common.Extensions
{
    public static class DependencyExtensions
    {
        public static readonly DependencyProperty<Timer> HeartbeatTimerProperty =
        DependencyProperty<Timer>.Register("HeartbeatTimer", null);
        public static bool CustomPing<TClient>(this TClient client) where TClient : ITcpClientBase
        {
            try
            {
                //模拟心跳上行   命令号：17
                //A5091600000117DC5A  
                //client.Send("A5091600000117DC5A".HexStringToByteArray());
                client.Send(new byte[] { 0xA5, 0x09, 0x16, 0x00, 0x00, 0x01, 0x17, 0xDC, 0x5A });
                return true;
            }
            catch (Exception ex)
            {
                client.Logger.Exception(ex);
            }

            return false;
        }

        public static bool CustomPong<TClient>(this TClient client, BetweenAndRequestInfo info) where TClient : ITcpClientBase
        {
            try
            {
                var Body = info.Body;
                var deviceIdStr = Convert.ToHexString(info.DeviceId);
                Consts.devices.TryAdd(deviceIdStr, new Device() { ScoketIPPort = client.IP + ":" + client.Port, State = 1 });

                Consts.CommandPackageLength.TryGetValue(DataType.心跳包应答下, out var packageLength);
                var buffer = new List<byte>() { Consts.StartByte, packageLength };

                buffer.AddRange(info.deviceId.HexStringToByteArray());
                buffer.Add(((int)DataType.心跳包应答下).ToByte());
                var vaildCode = buffer.GetVaildByteCode();
                buffer.Add(vaildCode);
                buffer.Add(Consts.EndByte);
                client.Send(buffer.ToArray());
                Console.WriteLine($"服务器 -> 客户端{deviceIdStr}   数据:{Convert.ToHexString(buffer.ToArray())}");
                return true;
            }
            catch (Exception ex)
            {
                client.Logger.Exception(ex);
            }

            return false;
        }


        public static bool AllPing<TClient>(this TClient client) where TClient : ITcpClientBase
        {
            //获取所有socket

            

            return true;
        }

        /// <summary>
        /// 查询设备状态命令（下行）
        /// </summary>
        /// <typeparam name="TClient"></typeparam>
        /// <param name="client"></param>
        /// <param name="info"></param>
        /// <returns></returns>
        public static bool SelectDeviedState<TClient>(this TClient client, BetweenAndRequestInfo info) where TClient : ITcpClientBase
        {
            //0A 00F42401 1D 05EA  
            var Body = info.Body;
            var startBytes = new List<byte>() { 0xA5, 0x09, Body[2], Body[3], Body[4], Body[5], ((int)DataType.设备应答查询上).ToByte() };
            var vaildCode = startBytes.GetVaildByteCode();
            startBytes.Add(vaildCode);
            startBytes.Add(Consts.EndByte);
            client.Send(startBytes.ToArray());
            return true;
        }

        /// <summary>
        /// 验证上行byte校验码
        /// </summary>
        /// <param name="ba"></param>
        /// <returns></returns>
        public static bool VaildByte(this byte[] ba)
        {
            byte vaildByte = Consts.StartByte;
            for (int i = 0; i < ba.Length - 1; i++)
            {
                vaildByte += ba[i];
            }
            return ((byte)(vaildByte & 0xFF)).Equals(ba[ba.Length - 1]);
        }

        /// <summary>
        /// 16进制字符串转byte数组
        /// </summary>
        /// <param name="hex"></param>
        /// <returns></returns>
        public static byte[] HexStringToByteArray(this string hex)
        {
            int length = hex.Length;
            byte[] byteArray = new byte[length / 2];

            for (int i = 0; i < length; i += 2)
            {
                byteArray[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
            }
            return byteArray;

        }

        public static string HexCharArrayToUTF8String(this char[] chars)
        {
            return new string(chars.ToArray()).HexStringToUTF8String();
        }

        public static string HexStringToUTF8String(this string hex)
        {
            return Encoding.UTF8.GetString(hex.ByHexStringToBytes());
        }

        /// <summary>
        /// 生成校验码
        /// </summary>
        /// <param name="bytes"></param>
        /// <returns></returns>
        public static byte GetVaildByteCode(this IEnumerable<byte> bytes)
        {
            if (bytes == null || bytes.Count() == 0)
                return 0;
            var cloneBytes = bytes.ToList();
            byte endBytes = 0;
            for (int i = 0; i < cloneBytes.Count(); i++)
            {
                endBytes += cloneBytes[i];
            }
            return (byte)(endBytes & 0xFF);
        }

        public static byte ToByte(this int num)
        {
            return Convert.ToByte(num);
            //if(num<0||num>=256)
            //{
            //    throw new ArgumentOutOfRangeException(nameof(num));
            //}

            //var numHex = num.ToString("X");
            //if (numHex.Length == 1)
            //{
            //    numHex = "0" + numHex;
            //}
            //return numHex.HexStringToByteArray()[0];
        }

        public static byte[] ToTwoByte(this int num)
        {
            var hex = num.ToString("X");
            var preLen = 4 - hex.Length;
            for (int i = 0; i < preLen; i++)
            {
                hex = "0" + hex;
            }
            if (hex.Length % 2 != 0)
                hex = "0" + hex;
            int byteCount = hex.Length / 2;
            byte[] bytes = new byte[byteCount];

            for (int i = 0; i < byteCount; i++)
            {
                string hexByte = hex.Substring(i * 2, 2);
                bytes[i] = Convert.ToByte(hexByte, 16);
            }
            return bytes;
        }

        #region 数据处理


        public static bool TryGetKey<T1, T2>(this ConcurrentDictionary<T1, T2> dic, T2 value, out T1 key)
        {
            key = default;
            try
            {
                if (dic is null)
                {
                    return false;
                }
                foreach (var k in dic.Keys)
                {
                    if (dic[k].Equals(value))
                    {
                        key = k;
                        return true;
                    }
                }
            }
            catch (Exception)
            {
            }
            return false;
        }

        #endregion
    }
}
